package World.Module.IdGenerator;

import World.ISingletonAwake;
import World.Module.Options.JOptions;
import World.Module.TimeInfo.TimeInfo;
import World.Singleton;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.concurrent.atomic.AtomicInteger;

public class IdGenerator extends Singleton implements ISingletonAwake {
    public static final int MaxZone = 1024;

    public static final int Mask14bit = 0x3fff;
    public static final int Mask30bit = 0x3fffffff;
    public static final int Mask20bit = 0xfffff;

    private long epoch2022;
    private int value;
    private int instanceIdValue;

    @Override
    public void Awake() {
        long epoch1970tick = LocalDateTime.of(1970, 1, 1, 0, 0, 0)
                .toInstant(ZoneOffset.UTC).toEpochMilli();
        this.epoch2022 = LocalDateTime.of(2022, 1, 1, 0, 0, 0)
                .toInstant(ZoneOffset.UTC).toEpochMilli() - epoch1970tick;
    }

    private int TimeSince2022()
    {
        int seconds = (int)((TimeInfo.<TimeInfo>GetInstance().GetFrameTime() - this.epoch2022) / 1000);
        return seconds;
    }

    public long GenerateId()
    {
        int time = TimeSince2022();
        int v = 0;

        synchronized (this)
        {
            if(++this.value > Mask20bit - 1) //value 取到了最大值，初始化0
            {
                this.value = 0;
            }
            v = this.value;
        }
        IdStruct idStruct = new IdStruct(time, (short) JOptions.<JOptions>GetInstance().process, v);
        return idStruct.ToLong();
    }

    public long GenerateInstanceId()
    {
        int time = this.TimeSince2022();
        int v = new AtomicInteger(this.instanceIdValue).addAndGet(1);
        InstanceIdStruct instanceIdStruct = new InstanceIdStruct(time, v);
        return instanceIdStruct.ToLong();
    }

}
